home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / elm2.2 / part12 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  49.3 KB

  1. Subject:  v18i091:  Elm mail system, release 2.2, Part12/24
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 91
  8. Archive-name: elm2.2/part12
  9.  
  10. #!/bin/sh
  11. # this is part 12 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file src/builtin.c continued
  14. #
  15. CurArch=12
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file src/builtin.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> src/builtin.c
  27. X    padding = COLUMNS - (t1_len + t2_len + strlen(title3));
  28. X
  29. X    sprintf(titlebuf, "%s%-*.*s%s\n\r\n\r", title1, t2_len+padding,
  30. X        t2_len+padding, title2, title3);
  31. X        /* extra newline is to give a blank line after title */
  32. X
  33. X    Write_to_screen(titlebuf, 0);
  34. X    form_title = 0;
  35. X}
  36. SHAR_EOF
  37. echo "File src/builtin.c is complete"
  38. chmod 0444 src/builtin.c || echo "restore of src/builtin.c fails"
  39. echo "x - extracting src/calendar.c (Text)"
  40. sed 's/^X//' << 'SHAR_EOF' > src/calendar.c &&
  41. X
  42. Xstatic char rcsid[] = "@(#)$Id: calendar.c,v 2.8 89/03/25 21:45:53 syd Exp $";
  43. X
  44. X/*******************************************************************************
  45. X *  The Elm Mail System  -  $Revision: 2.8 $   $State: Exp $
  46. X *
  47. X *             Copyright (c) 1986, 1987 Dave Taylor
  48. X *             Copyright (c) 1988, 1989 USENET Community Trust
  49. X *******************************************************************************
  50. X * Bug reports, patches, comments, suggestions should be sent to:
  51. X *
  52. X *    Syd Weinstein, Elm Coordinator
  53. X *    elm@dsinc.UUCP            dsinc!elm
  54. X *
  55. X *******************************************************************************
  56. X * $Log:    calendar.c,v $
  57. X * Revision 2.8  89/03/25  21:45:53  syd
  58. X * Initial 2.2 Release checkin
  59. X * 
  60. X *
  61. X ******************************************************************************/
  62. X
  63. X/** This routine implements a rather snazzy idea suggested by Warren
  64. X    Carithers of the Rochester Institute of Technology that allows
  65. X    mail to contain entries formatted in a manner that will allow direct
  66. X    copying into a users calendar program.
  67. X
  68. X    All lines in the current message beginning with "->", e.g.
  69. X
  70. X    -> Mon 04/21 1:00p meet with chairman candidate
  71. X
  72. X    get copied into the user's calendar file.
  73. X
  74. X**/
  75. X
  76. X#include "headers.h"
  77. X
  78. X#ifdef ENABLE_CALENDAR        /* if not defined, this will be an empty file */
  79. X
  80. X#include <errno.h>
  81. X
  82. Xextern int errno;
  83. X
  84. Xchar *error_name(), *error_description(), *strcpy();
  85. X
  86. Xscan_calendar()
  87. X{
  88. X    FILE *calendar;
  89. X    int  count;
  90. X
  91. X    /* First step is to open the calendar file for appending... **/
  92. X
  93. X    if (can_open(calendar_file, "a") != 0) {
  94. X      dprint(2, (debugfile,
  95. X          "Error: wrong permissions to append to calendar %s\n",
  96. X          calendar_file));
  97. X      dprint(2, (debugfile, "** %s - %s **\n",
  98. X          error_name(errno), error_description(errno)));
  99. X      error1("Not able to append to file %s!", calendar_file);
  100. X      return; 
  101. X    }
  102. X
  103. X    save_file_stats(calendar_file);
  104. X
  105. X    if ((calendar = fopen(calendar_file,"a")) == NULL) {
  106. X      dprint(2, (debugfile, 
  107. X        "Error: couldn't append to calendar file %s (scan)\n", 
  108. X        calendar_file));
  109. X      dprint(2, (debugfile, "** %s - %s **\n",
  110. X          error_name(errno), error_description(errno)));
  111. X      error1("Couldn't append to file %s!", calendar_file);
  112. X      return; 
  113. X    }
  114. X    
  115. X    count = extract_info(calendar);
  116. X
  117. X    fclose(calendar);
  118. X
  119. X    restore_file_stats(calendar_file);
  120. X
  121. X    if (count > 0)
  122. X      error2("%d entr%s saved in calendar file.", 
  123. X         count, count > 1 ? "ies" : "y");
  124. X    else 
  125. X      error("No calendar entries found in that message.");
  126. X
  127. X    return;
  128. X}
  129. X
  130. Xint
  131. Xextract_info(save_to_fd)
  132. XFILE *save_to_fd;
  133. X{
  134. X    /** Save the relevant parts of the current message to the given
  135. X        calendar file.  The only parameter is an opened file
  136. X        descriptor, positioned at the end of the existing file **/
  137. X        
  138. X    register int entries = 0, lines;
  139. X    char buffer[SLEN], *cp, *is_cal_entry();
  140. X
  141. X        /** get to the first line of the message desired **/
  142. X
  143. X        if (fseek(mailfile, headers[current-1]->offset, 0) == -1) {
  144. X             dprint(1,(debugfile, 
  145. X        "ERROR: Attempt to seek %d bytes into file failed (%s)",
  146. X        headers[current-1]->offset, "extract_info"));
  147. X             error1("ELM [seek] failed trying to read %d bytes into file.",
  148. X             headers[current-1]->offset);
  149. X             return(0);
  150. X        }
  151. X
  152. X        /* how many lines in message? */
  153. X
  154. X        lines = headers[current-1]->lines;
  155. X
  156. X        /* now while not EOF & still in message... scan it! */
  157. X
  158. X    while (lines) {
  159. X
  160. X          if(fgets(buffer, SLEN, mailfile) == NULL)
  161. X        break;
  162. X
  163. X      if(buffer[strlen(buffer)-1] == '\n')
  164. X        lines--;                    /* got a full line */
  165. X
  166. X      if((cp = is_cal_entry(buffer)) != NULL) {
  167. X        entries++;
  168. X        fprintf(save_to_fd,"%s", cp);
  169. X      }
  170. X
  171. X    }
  172. X    dprint(4,(debugfile,
  173. X        "Got %d calender entr%s.\n", entries, entries > 1? "ies":"y"));
  174. X
  175. X    return(entries);
  176. X}
  177. X
  178. Xchar *
  179. Xis_cal_entry(string)
  180. Xregister char *string;
  181. X{
  182. X    /* If string is of the form
  183. X     *    ->{optional white space} {stuff}
  184. X     * return a pointer to stuff, otherwise return NULL.
  185. X     */
  186. X    
  187. X    if(strncmp(string, "->", 2) == 0) {
  188. X      for(string +=2 ; whitespace(*string); string++)
  189. X          ;
  190. X      return(string);
  191. X    }
  192. X    return(NULL);
  193. X}
  194. X
  195. X#endif
  196. SHAR_EOF
  197. chmod 0444 src/calendar.c || echo "restore of src/calendar.c fails"
  198. echo "x - extracting src/conn_to.c (Text)"
  199. sed 's/^X//' << 'SHAR_EOF' > src/conn_to.c &&
  200. X
  201. Xstatic char rcsid[] = "@(#)$Id: conn_to.c,v 2.3 89/03/25 21:45:54 syd Exp $";
  202. X
  203. X/*******************************************************************************
  204. X *  The Elm Mail System  -  $Revision: 2.3 $   $State: Exp $
  205. X *
  206. X *             Copyright (c) 1986, 1987 Dave Taylor
  207. X *             Copyright (c) 1988, 1989 USENET Community Trust
  208. X *******************************************************************************
  209. X * Bug reports, patches, comments, suggestions should be sent to:
  210. X *
  211. X *    Syd Weinstein, Elm Coordinator
  212. X *    elm@dsinc.UUCP            dsinc!elm
  213. X *
  214. X *******************************************************************************
  215. X * $Log:    conn_to.c,v $
  216. X * Revision 2.3  89/03/25  21:45:54  syd
  217. X * Initial 2.2 Release checkin
  218. X * 
  219. X *
  220. X ******************************************************************************/
  221. X
  222. X/** This contains the routine(s) needed to have the Elm mailer figure
  223. X    out what machines the current machine can talk to.   This can be
  224. X    done in one of two ways - either the program can read the L.sys
  225. X    file, or (if it fails or "UUNAME" define is present) will invoke
  226. X    uuname to a file, then read the file in!
  227. X
  228. X**/
  229. X
  230. X#include "headers.h"
  231. X
  232. Xchar *strcpy();
  233. X
  234. Xget_connections()
  235. X{
  236. X
  237. X    /** get the direct connections that this machine has, by hook
  238. X        or by crook (so to speak) 
  239. X    **/
  240. X
  241. X#ifndef USE_UUNAME
  242. X    FILE *lsysfile;
  243. X    char  buffer[SLEN], sysname[NLEN];
  244. X    struct lsys_rec *system_record, *previous_record;
  245. X    int    loc_on_line;
  246. X#endif
  247. X
  248. X    if (! warnings) {        /* skip this - they don't care! */
  249. X      talk_to_sys = NULL;
  250. X      return;
  251. X    }
  252. X
  253. X#ifndef USE_UUNAME
  254. X
  255. X    previous_record = NULL;
  256. X    if ((lsysfile = fopen(Lsys,"r")) == NULL) {
  257. X      dprint(1, (debugfile, 
  258. X        "Warning: Can't open L.sys file %s (read_lsys)\n", Lsys));
  259. X#endif
  260. X
  261. X      if (read_uuname() == -1) {
  262. X        error("Warning: couldn't figure out system connections...");
  263. X        talk_to_sys = NULL;
  264. X      }
  265. X
  266. X#ifndef USE_UUNAME
  267. X      /** ELSE: already read in uuname() output if we're here!! **/
  268. X      return;
  269. X    }
  270. X
  271. X    while (fgets(buffer, SLEN, lsysfile) != NULL) {
  272. X      sscanf(buffer,"%s", sysname);
  273. X
  274. X      if (previous_record == NULL) {
  275. X        dprint(2, (debugfile, 
  276. X        "L.sys\tdirect connection to %s, ", sysname));
  277. X        loc_on_line = 30 + strlen(sysname);  
  278. X        previous_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys);
  279. X
  280. X        strcpy(previous_record->name, sysname);
  281. X        previous_record->next = NULL;
  282. X        talk_to_sys = previous_record;
  283. X      }
  284. X      else if (! talk_to(sysname) && sysname[0] != '#') {
  285. X        if (loc_on_line + strlen(sysname) > 80) {
  286. X          dprint(2, (debugfile, "\n\t"));
  287. X          loc_on_line = 8;
  288. X        }
  289. X        dprint(2, (debugfile, "%s, ", sysname));
  290. X        loc_on_line += (strlen(sysname) + 2);
  291. X        system_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys);
  292. X      
  293. X        strcpy(system_record->name, sysname);
  294. X        system_record->next = NULL;
  295. X        previous_record->next = system_record;
  296. X        previous_record = system_record;
  297. X      }
  298. X    }
  299. X
  300. X    fclose(lsysfile);
  301. X
  302. X    if (loc_on_line != 8)
  303. X      dprint(2, (debugfile, "\n"));
  304. X
  305. X    dprint(2, (debugfile, "\n"));    /* for an even nicer format... */
  306. X#endif
  307. X}
  308. X
  309. Xint
  310. Xread_uuname()
  311. X{
  312. X    /** This routine trys to use the uuname routine to get the names of
  313. X        all the machines that this machine connects to...it returns
  314. X        -1 on failure.
  315. X    **/
  316. X
  317. X    FILE *fd;
  318. X    char  buffer[SLEN], filename[SLEN];
  319. X    struct lsys_rec *system_record, *previous_record;
  320. X    int   loc_on_line;
  321. X
  322. X    sprintf(filename, "%s%d", temp_uuname, getpid());
  323. X    sprintf(buffer,"%s > %s", uuname, filename);
  324. X
  325. X    if (system_call(buffer, SH, FALSE) != 0) {
  326. X      dprint(1, (debugfile, "Can't get uuname info - system() failed!\n"));
  327. X      unlink(filename);    /* insurance */
  328. X      return(-1);
  329. X    }
  330. X    
  331. X    if ((fd = fopen(filename, "r")) == NULL) {
  332. X      dprint(1, (debugfile,
  333. X        "Can't get uuname info - can't open file %s for reading\n",
  334. X         filename));
  335. X      unlink(filename);    /* insurance */
  336. X      return(-1);
  337. X    }
  338. X    
  339. X    previous_record = NULL;
  340. X
  341. X    while (fgets(buffer, SLEN, fd) != NULL) {
  342. X      no_ret(buffer);
  343. X      if (previous_record == NULL) {
  344. X        dprint(2, (debugfile, "uuname\tdirect connection to %s, ", buffer));
  345. X        loc_on_line = 30 + strlen(buffer);
  346. X        previous_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys);
  347. X
  348. X        strcpy(previous_record->name, buffer);
  349. X        previous_record->next = NULL;
  350. X        talk_to_sys = previous_record;
  351. X      }
  352. X      else {    /* don't have to check uniqueness - uuname does that! */
  353. X        if (loc_on_line + strlen(buffer) > 80) {
  354. X          dprint(2, (debugfile, "\n\t"));
  355. X          loc_on_line = 8;
  356. X        }
  357. X        dprint(2, (debugfile, "%s, ", buffer));
  358. X        loc_on_line += (strlen(buffer) + 2);
  359. X        system_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys);
  360. X      
  361. X        strcpy(system_record->name, buffer);
  362. X        system_record->next = NULL;
  363. X        previous_record->next = system_record;
  364. X        previous_record = system_record;
  365. X      }
  366. X    }
  367. X
  368. X    fclose(fd);
  369. X
  370. X    (void) unlink(filename);        /* kill da temp file!! */
  371. X
  372. X    dprint(2, (debugfile, "\n"));        /* for a nice format! Yeah! */
  373. X
  374. X    return(0);                /* it all went okay... */
  375. X}
  376. SHAR_EOF
  377. chmod 0444 src/conn_to.c || echo "restore of src/conn_to.c fails"
  378. echo "x - extracting src/curses.c (Text)"
  379. sed 's/^X//' << 'SHAR_EOF' > src/curses.c &&
  380. X
  381. Xstatic char rcsid[] = "@(#)$Id: curses.c,v 2.15 89/03/25 21:45:56 syd Exp $";
  382. X
  383. X/*******************************************************************************
  384. X *  The Elm Mail System  -  $Revision: 2.15 $   $State: Exp $
  385. X *
  386. X *             Copyright (c) 1986, 1987 Dave Taylor
  387. X *             Copyright (c) 1988, 1989 USENET Community Trust
  388. X *******************************************************************************
  389. X * Bug reports, patches, comments, suggestions should be sent to:
  390. X *
  391. X *    Syd Weinstein, Elm Coordinator
  392. X *    elm@dsinc.UUCP            dsinc!elm
  393. X *
  394. X *******************************************************************************
  395. X * $Log:    curses.c,v $
  396. X * Revision 2.15  89/03/25  21:45:56  syd
  397. X * Initial 2.2 Release checkin
  398. X * 
  399. X *
  400. X ******************************************************************************/
  401. X
  402. X/**  This library gives programs the ability to easily access the
  403. X     termcap information and write screen oriented and raw input
  404. X     programs.  The routines can be called as needed, except that
  405. X     to use the cursor / screen routines there must be a call to
  406. X     InitScreen() first.  The 'Raw' input routine can be used
  407. X     independently, however.
  408. X
  409. X**/
  410. X
  411. X/** NOTE THE ADDITION OF: the #ifndef ELM stuff around routines that
  412. X    we don't use.  This is for code size and compile time speed...
  413. X**/
  414. X
  415. X#include "headers.h"
  416. X
  417. X#ifdef TERMIO
  418. X#  include <termio.h>
  419. X#else
  420. X#  include <sgtty.h>
  421. X#endif
  422. X
  423. X#include <ctype.h>
  424. X
  425. X#ifdef BSD
  426. X#undef tolower
  427. X#endif
  428. X
  429. X#define TTYIN    0
  430. X
  431. X#ifdef SHORTNAMES
  432. X# define _clearinverse    _clrinv
  433. X# define _cleartoeoln    _clrtoeoln
  434. X# define _cleartoeos    _clr2eos
  435. X# define _transmit_off    xmit_off
  436. X# define _transmit_on    xmit_on
  437. X#endif
  438. X
  439. X#ifdef TERMIO
  440. Xstruct termio _raw_tty, 
  441. X              _original_tty;
  442. X#else
  443. X#    define TCGETA    TIOCGETP
  444. X#    define TCSETAW    TIOCSETP
  445. X
  446. Xstruct sgttyb _raw_tty,
  447. X          _original_tty;
  448. X#endif
  449. X
  450. Xstatic int _inraw = 0;                  /* are we IN rawmode?    */
  451. X
  452. X#define DEFAULT_LINES_ON_TERMINAL    24
  453. X#define DEFAULT_COLUMNS_ON_TERMINAL    80
  454. X
  455. Xstatic int _memory_locked = 0;        /* are we IN memlock??   */
  456. Xstatic int _line  = -1,            /* initialize to "trash" */
  457. X           _col   = -1;
  458. X
  459. Xstatic int _intransmit;            /* are we transmitting keys? */
  460. X
  461. Xstatic
  462. Xchar *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
  463. X     *_setbold, *_clearbold, *_setunderline, *_clearunderline, 
  464. X     *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
  465. X     *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off,
  466. X     *_set_memlock, *_clear_memlock;
  467. X
  468. Xstatic int _lines, _columns, _automargin, _eatnewlineglitch;
  469. Xint tabspacing;
  470. X
  471. Xstatic char _terminal[1024];              /* Storage for terminal entry */
  472. Xstatic char _capabilities[1024];           /* String for cursor motion */
  473. X
  474. Xstatic char *ptr = _capabilities;    /* for buffering         */
  475. X
  476. Xint    outchar();            /* char output for tputs */
  477. Xchar  *tgetstr(),                    /* Get termcap capability */
  478. X      *tgoto();                /* and the goto stuff    */
  479. X
  480. XInitScreen()
  481. X{
  482. X    /* Set up all this fun stuff: returns zero if all okay, or;
  483. X        -1 indicating no terminal name associated with this shell,
  484. X        -2..-n  No termcap for this terminal type known
  485. X   */
  486. X
  487. X    int  tgetent(),      /* get termcap entry */
  488. X         err;
  489. X    char termname[40];
  490. X    char *strcpy(), *getenv();
  491. X    
  492. X    if (getenv("TERM") == NULL) return(-1);
  493. X
  494. X    if (strcpy(termname, getenv("TERM")) == NULL)
  495. X        return(-1);
  496. X
  497. X    if ((err = tgetent(_terminal, termname)) != 1)
  498. X        return(err-2);
  499. X
  500. X    _line  =  0;        /* where are we right now?? */
  501. X    _col   =  0;        /* assume zero, zero...     */
  502. X
  503. X    /* load in all those pesky values */
  504. X    _clearscreen       = tgetstr("cl", &ptr);
  505. X    _moveto            = tgetstr("cm", &ptr);
  506. X    _up                = tgetstr("up", &ptr);
  507. X    _down              = tgetstr("do", &ptr);
  508. X    _right             = tgetstr("nd", &ptr);
  509. X    _left              = tgetstr("bs", &ptr);
  510. X    _setbold           = tgetstr("so", &ptr);
  511. X    _clearbold         = tgetstr("se", &ptr);
  512. X    _setunderline      = tgetstr("us", &ptr);
  513. X    _clearunderline    = tgetstr("ue", &ptr);
  514. X    _setinverse        = tgetstr("so", &ptr);
  515. X    _clearinverse      = tgetstr("se", &ptr);
  516. X    _sethalfbright     = tgetstr("hs", &ptr);
  517. X    _clearhalfbright   = tgetstr("he", &ptr);
  518. X    _cleartoeoln       = tgetstr("ce", &ptr);
  519. X    _cleartoeos        = tgetstr("cd", &ptr);
  520. X    _lines                 = tgetnum("li");
  521. X    _columns       = tgetnum("co");
  522. X    tabspacing       = ((tabspacing=tgetnum("it"))==-1 ? 8 : tabspacing);
  523. X    _automargin       = tgetflag("am");
  524. X    _eatnewlineglitch   = tgetflag("xn");
  525. X    _transmit_on       = tgetstr("ks", &ptr);
  526. X    _transmit_off      = tgetstr("ke", &ptr);
  527. X    _set_memlock       = tgetstr("ml", &ptr);
  528. X    _clear_memlock       = tgetstr("mu", &ptr);
  529. X
  530. X
  531. X    if (!_left) {
  532. X        _left = "\b";
  533. X    }
  534. X
  535. X    return(0);
  536. X}
  537. X
  538. Xchar *return_value_of(termcap_label)
  539. Xchar *termcap_label;
  540. X{
  541. X    /** This will return the string kept by termcap for the 
  542. X        specified capability. Modified to ensure that if 
  543. X        tgetstr returns a pointer to a transient address    
  544. X        that we won't bomb out with a later segmentation
  545. X        fault (thanks to Dave@Infopro for this one!)
  546. X
  547. X        Tweaked to remove padding sequences.
  548. X     **/
  549. X
  550. X    static char escape_sequence[20];
  551. X    register int i=0,j=0;
  552. X    char buffer[20];
  553. X    char *myptr, *tgetstr();             /* Get termcap capability */
  554. X
  555. X    if (strlen(termcap_label) < 2)
  556. X      return(NULL);
  557. X
  558. X    if (termcap_label[0] == 's' && termcap_label[1] == 'o')
  559. X      {
  560. X      if (_setinverse)
  561. X        strcpy(escape_sequence, _setinverse);
  562. X      else
  563. X        return( (char *) NULL );
  564. X      }
  565. X    else if (termcap_label[0] == 's' && termcap_label[1] == 'e')
  566. X      {
  567. X      if (_clearinverse)
  568. X        strcpy(escape_sequence, _clearinverse);
  569. X      else
  570. X        return( (char *) NULL );
  571. X      }
  572. X    else if ((myptr = tgetstr(termcap_label, &ptr)) == NULL)
  573. X      return( (char *) NULL );
  574. X    else
  575. X      strcpy(escape_sequence, myptr);
  576. X
  577. X    if (chloc(escape_sequence, '$') != -1) {
  578. X      while (escape_sequence[i] != '\0') {
  579. X        while (escape_sequence[i] != '$' && escape_sequence[i] != '\0')
  580. X          buffer[j++] = escape_sequence[i++];
  581. X        if (escape_sequence[i] == '$') {
  582. X          while (escape_sequence[i] != '>') i++;
  583. X          i++;
  584. X        }
  585. X      }
  586. X      buffer[j] = '\0';
  587. X      strcpy(escape_sequence, buffer);
  588. X    }
  589. X
  590. X    return( (char *) escape_sequence);
  591. X}
  592. X
  593. Xtransmit_functions(newstate)
  594. Xint newstate;
  595. X{
  596. X    /** turn function key transmission to ON | OFF **/
  597. X
  598. X    if (newstate != _intransmit) {
  599. X        _intransmit = ! _intransmit;
  600. X        if (newstate == ON)
  601. X          tputs(_transmit_on, 1, outchar);
  602. X        else 
  603. X          tputs(_transmit_off, 1, outchar);
  604. X        fflush(stdout);      /* clear the output buffer */
  605. X    }
  606. X}
  607. X
  608. X/****** now into the 'meat' of the routines...the cursor stuff ******/
  609. X
  610. XScreenSize(lines, columns)
  611. Xint *lines, *columns;
  612. X{
  613. X    /** returns the number of lines and columns on the display. **/
  614. X
  615. X    if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  616. X    if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  617. X
  618. X    *lines = _lines - 1;        /* assume index from zero */
  619. X    *columns = _columns;
  620. X}
  621. X
  622. XSetXYLocation(x,y)
  623. Xint x,y;
  624. X{
  625. X    /* declare where the cursor is on the screen - useful after using
  626. X     * a function that moves cursor in predictable fasion but doesn't
  627. X     * set the static x and y variables used in this source file -
  628. X     * e.g. getpass().
  629. X     */
  630. X
  631. X    _line = x;
  632. X    _col = y;
  633. X}
  634. X
  635. XGetXYLocation(x,y)
  636. Xint *x,*y;
  637. X{
  638. X    /* return the current cursor location on the screen */
  639. X
  640. X    *x = _line;
  641. X    *y = _col;
  642. X}
  643. X
  644. XClearScreen()
  645. X{
  646. X    /* clear the screen: returns -1 if not capable */
  647. X
  648. X    _line = 0;    /* clear leaves us at top... */
  649. X    _col  = 0;
  650. X
  651. X    if (!_clearscreen)
  652. X        return(-1);
  653. X
  654. X    tputs(_clearscreen, 1, outchar);
  655. X    fflush(stdout);      /* clear the output buffer */
  656. X    return(0);
  657. X}
  658. X
  659. Xstatic
  660. Xmoveabsolute(col, row)
  661. X{
  662. X
  663. X    char *stuff, *tgoto();
  664. X
  665. X    stuff = tgoto(_moveto, col, row);
  666. X    tputs(stuff, 1, outchar);
  667. X    fflush(stdout);
  668. X}
  669. X
  670. XMoveCursor(row, col)
  671. Xint row, col;
  672. X{
  673. X    /** move cursor to the specified row column on the screen.
  674. X            0,0 is the top left! **/
  675. X
  676. X    int scrollafter = 0;
  677. X
  678. X    /* we don't want to change "rows" or we'll mangle scrolling... */
  679. X
  680. X    if (col < 0)
  681. X      col = 0;
  682. X    if (col >= COLUMNS)
  683. X      col = COLUMNS - 1;
  684. X    if (row < 0)
  685. X      row = 0;
  686. X    if (row > LINES) {
  687. X      if (col == 0)
  688. X        scrollafter = row - LINES;
  689. X      row = LINES;
  690. X    }
  691. X
  692. X    if (!_moveto)
  693. X        return(-1);
  694. X
  695. X    if (row == _line) {
  696. X      if (col == _col)
  697. X        return(0);                /* already there! */
  698. X
  699. X      else if (abs(col - _col) < 5) {    /* within 5 spaces... */
  700. X        if (col > _col && _right)
  701. X          CursorRight(col - _col);
  702. X        else if (col < _col &&  _left)
  703. X          CursorLeft(_col - col);
  704. X        else
  705. X          moveabsolute(col, row);
  706. X          }
  707. X      else         /* move along to the new x,y loc */
  708. X        moveabsolute(col, row);
  709. X    }
  710. X    else if (col == _col && abs(row - _line) < 5) {
  711. X      if (row < _line && _up)
  712. X        CursorUp(_line - row);
  713. X      else if (_line > row && _down)
  714. X        CursorDown(row - _line);
  715. X      else
  716. X        moveabsolute(col, row);
  717. X    }
  718. X    else if (_line == row-1 && col == 0) {
  719. X      putchar('\n');    /* that's */
  720. X      putchar('\r');    /*  easy! */
  721. X      fflush(stdout);
  722. X    }
  723. X    else 
  724. X      moveabsolute(col, row);
  725. X
  726. X    _line = row;    /* to ensure we're really there... */
  727. X    _col  = col;
  728. X
  729. X    if (scrollafter) {
  730. X      while (scrollafter--) {
  731. X        putchar('\n');
  732. X        putchar('\r');
  733. X      }
  734. X    }
  735. X
  736. X    return(0);
  737. X}
  738. X
  739. XCarriageReturn()
  740. X{
  741. X    /** move the cursor to the beginning of the current line **/
  742. X    Writechar('\r');
  743. X}
  744. X
  745. XNewLine()
  746. X{
  747. X    /** move the cursor to the beginning of the next line **/
  748. X
  749. X    Writechar('\n');
  750. X    Writechar('\r');
  751. X}
  752. X
  753. Xstatic
  754. XCursorUp(n)
  755. Xint n;
  756. X{
  757. X    /** move the cursor up 'n' lines **/
  758. X    /** Calling function must check that _up is not null before calling **/
  759. X
  760. X    _line = (_line-n > 0? _line - n: 0);    /* up 'n' lines... */
  761. X
  762. X    while (n-- > 0)
  763. X        tputs(_up, 1, outchar);
  764. X
  765. X    fflush(stdout);
  766. X    return(0);
  767. X}
  768. X
  769. X
  770. Xstatic
  771. XCursorDown(n)
  772. Xint n;
  773. X{
  774. X    /** move the cursor down 'n' lines **/
  775. X    /** Caller must check that _down is not null before calling **/
  776. X
  777. X    _line = (_line+n < LINES? _line + n: LINES);    /* down 'n' lines... */
  778. X
  779. X    while (n-- > 0)
  780. X        tputs(_down, 1, outchar);
  781. X
  782. X    fflush(stdout);
  783. X    return(0);
  784. X}
  785. X
  786. X
  787. Xstatic
  788. XCursorLeft(n)
  789. Xint n;
  790. X{
  791. X    /** move the cursor 'n' characters to the left **/
  792. X    /** Caller must check that _left is not null before calling **/
  793. X
  794. X    _col = (_col - n> 0? _col - n: 0);    /* left 'n' chars... */
  795. X
  796. X    while (n-- > 0)
  797. X        tputs(_left, 1, outchar);
  798. X
  799. X    fflush(stdout);
  800. X    return(0);
  801. X}
  802. X
  803. X
  804. Xstatic
  805. XCursorRight(n)
  806. Xint n;
  807. X{
  808. X    /** move the cursor 'n' characters to the right (nondestructive) **/
  809. X    /** Caller must check that _right is not null before calling **/
  810. X
  811. X    _col = (_col+n < COLUMNS? _col + n: COLUMNS);    /* right 'n' chars... */
  812. X
  813. X    while (n-- > 0)
  814. X        tputs(_right, 1, outchar);
  815. X
  816. X    fflush(stdout);
  817. X    return(0);
  818. X}
  819. X
  820. X
  821. XStartBold()
  822. X{
  823. X    /** start boldface/standout mode **/
  824. X
  825. X    if (!_setbold)
  826. X        return(-1);
  827. X
  828. X    tputs(_setbold, 1, outchar);
  829. X    fflush(stdout);
  830. X    return(0);
  831. X}
  832. X
  833. X
  834. XEndBold()
  835. X{
  836. X    /** compliment of startbold **/
  837. X
  838. X    if (!_clearbold)
  839. X        return(-1);
  840. X
  841. X    tputs(_clearbold, 1, outchar);
  842. X    fflush(stdout);
  843. X    return(0);
  844. X}
  845. X
  846. X#ifndef ELM
  847. X
  848. XStartUnderline()
  849. X{
  850. X    /** start underline mode **/
  851. X
  852. X    if (!_setunderline)
  853. X        return(-1);
  854. X
  855. X    tputs(_setunderline, 1, outchar);
  856. X    fflush(stdout);
  857. X    return(0);
  858. X}
  859. X
  860. X
  861. XEndUnderline()
  862. X{
  863. X    /** the compliment of start underline mode **/
  864. X
  865. X    if (!_clearunderline)
  866. X        return(-1);
  867. X
  868. X    tputs(_clearunderline, 1, outchar);
  869. X    fflush(stdout);
  870. X    return(0);
  871. X}
  872. X
  873. X
  874. XStartHalfbright()
  875. X{
  876. X    /** start half intensity mode **/
  877. X
  878. X    if (!_sethalfbright)
  879. X        return(-1);
  880. X
  881. X    tputs(_sethalfbright, 1, outchar);
  882. X    fflush(stdout);
  883. X    return(0);
  884. X}
  885. X
  886. XEndHalfbright()
  887. X{
  888. X    /** compliment of starthalfbright **/
  889. X
  890. X    if (!_clearhalfbright)
  891. X        return(-1);
  892. X
  893. X    tputs(_clearhalfbright, 1, outchar);
  894. X    fflush(stdout);
  895. X    return(0);
  896. X}
  897. X
  898. XStartInverse()
  899. X{
  900. X    /** set inverse video mode **/
  901. X
  902. X    if (!_setinverse)
  903. X        return(-1);
  904. X
  905. X    tputs(_setinverse, 1, outchar);
  906. X    fflush(stdout);
  907. X    return(0);
  908. X}
  909. X
  910. X
  911. XEndInverse()
  912. X{
  913. X    /** compliment of startinverse **/
  914. X
  915. X    if (!_clearinverse)
  916. X        return(-1);
  917. X
  918. X    tputs(_clearinverse, 1, outchar);
  919. X    fflush(stdout);
  920. X    return(0);
  921. X}
  922. X
  923. Xint
  924. XHasMemlock()
  925. X{
  926. X    /** returns TRUE iff memory locking is available (a terminal
  927. X        feature that allows a specified portion of the screen to
  928. X        be "locked" & not cleared/scrolled... **/
  929. X
  930. X    return ( _set_memlock && _clear_memlock );
  931. X}
  932. X
  933. Xstatic int _old_LINES;
  934. X
  935. Xint
  936. XStartMemlock()
  937. X{
  938. X    /** mark the current line as the "last" line of the portion to 
  939. X        be memory locked (always relative to the top line of the
  940. X        screen) Note that this will alter LINES so that it knows
  941. X        the top is locked.  This means that (plus) the program 
  942. X        will scroll nicely but (minus) End memlock MUST be called
  943. X        whenever we leave the locked-memory part of the program! **/
  944. X
  945. X    if (! _set_memlock)
  946. X      return(-1);
  947. X
  948. X    if (! _memory_locked) {
  949. X
  950. X      _old_LINES = LINES;
  951. X      LINES -= _line;        /* we can't use this for scrolling */
  952. X
  953. X      tputs(_set_memlock, 1, outchar);
  954. X      fflush(stdout);
  955. X      _memory_locked = TRUE;
  956. X    }
  957. X
  958. X    return(0);
  959. X}
  960. X
  961. Xint
  962. XEndMemlock()
  963. X{
  964. X    /** Clear the locked memory condition...  **/
  965. X
  966. X    if (! _set_memlock)
  967. X      return(-1);
  968. X
  969. X    if (_memory_locked) {
  970. X      LINES = _old_LINES;        /* back to old setting */
  971. X  
  972. X      tputs(_clear_memlock, 1, outchar);
  973. X      fflush(stdout);
  974. X      _memory_locked = FALSE;
  975. X    }
  976. X    return(0);
  977. X}
  978. X
  979. X#endif /* ndef ELM */
  980. X
  981. XWritechar(ch)
  982. Xregister int ch;
  983. X{
  984. X    /** write a character to the current screen location. **/
  985. X
  986. X    static int autonewlinedlastchar = 0;
  987. X    register int justautonewlined, nt;
  988. X
  989. X    justautonewlined = 0;
  990. X
  991. X    /* if newline and terminal just did a newline without our asking,
  992. X     * do nothing, else output a newline and increment the line count */
  993. X    if(ch == '\n') {
  994. X      if (!autonewlinedlastchar) {
  995. X        putchar('\n');
  996. X        _line = min(_line+1, LINES-1);
  997. X      }
  998. X
  999. X    /* if return, move to column 0 */
  1000. X    } else if(ch == '\r') {
  1001. X      putchar('\r');
  1002. X      _col = 0;
  1003. X
  1004. X    /* if backspace, move back  one space  if not already in column 0 */
  1005. X    } else if (ch == BACKSPACE) {
  1006. X      if(_col != 0) {
  1007. X        putchar('\b');
  1008. X        _col--;
  1009. X      } /* else BACKSPACE does nothing */
  1010. X
  1011. X    /* if bell, ring the bell but don't advance the column */
  1012. X    } else if (ch == '\007') {
  1013. X      putchar(ch);
  1014. X
  1015. X
  1016. X    /* if a tab, output it */
  1017. X    } else if (ch == '\t') {
  1018. X      putchar(ch);
  1019. X      if((nt=next_tab(_col+1)) > prev_tab(COLUMNS))
  1020. X        _col = nt-1;
  1021. X      else
  1022. X        _col = COLUMNS-1;
  1023. X
  1024. X    } else {
  1025. X
  1026. X      /* if some kind of control or  non ascii character change to a '?' */
  1027. X      if(iscntrl(ch) || !isascii(ch))
  1028. X        ch = '?';
  1029. X
  1030. X      /* if we have no columns left and this terminal doesn't do
  1031. X       * automargins, simulate automargins and output the character */
  1032. X      if(_col == COLUMNS  && !_automargin) {
  1033. X        NewLine();
  1034. X        putchar(ch);
  1035. X        _col++;
  1036. X
  1037. X      /* if we only have one column left and if this is a terminal
  1038. X       * that automargins when the last column is written to, then
  1039. X       * output the char, and note that the automargin occurred */
  1040. X      } else if(_col+1 == COLUMNS && _automargin && !_eatnewlineglitch) {
  1041. X        putchar(ch);
  1042. X        _line = min(_line+1, LINES);
  1043. X        _col = 1;
  1044. X        justautonewlined = 1;
  1045. X
  1046. X      /* if we are already in the last column and we got here,
  1047. X       * this has to be a terminal with  automargin and the eatnewline
  1048. X       * glitch. Output the char and note that we are now in the
  1049. X       * 2nd column of the next line, since the terminal will do the
  1050. X       * automargin before displaying the character. */
  1051. X      } else if (_col == COLUMNS) {
  1052. X        putchar(ch);
  1053. X        _line = min(_line+1, LINES);
  1054. X        _col = 1;
  1055. X
  1056. X      /* if we are here this means we have no interference from the
  1057. X       * right margin - just output the character and increment the
  1058. X       * column position. */
  1059. X      } else {
  1060. X        putchar(ch);
  1061. X        _col++;
  1062. X      }
  1063. X    }
  1064. X    autonewlinedlastchar = justautonewlined;
  1065. X    return(0);
  1066. X}
  1067. X
  1068. X/*VARARGS2*/
  1069. X
  1070. XWrite_to_screen(line, argcount, arg1, arg2, arg3)
  1071. Xchar *line;
  1072. Xint   argcount; 
  1073. Xchar *arg1, *arg2, *arg3;
  1074. X{
  1075. X    /** This routine writes to the screen at the current location.
  1076. X          when done, it increments lines & columns accordingly by
  1077. X        looking for "\n" sequences... **/
  1078. X
  1079. X    switch (argcount) {
  1080. X    case 0 :
  1081. X        PutLine0(_line, _col, line);
  1082. X        break;
  1083. X    case 1 :
  1084. X        PutLine1(_line, _col, line, arg1);
  1085. X        break;
  1086. X    case 2 :
  1087. X        PutLine2(_line, _col, line, arg1, arg2);
  1088. X        break;
  1089. X    case 3 :
  1090. X        PutLine3(_line, _col, line, arg1, arg2, arg3);
  1091. X        break;
  1092. X    }
  1093. X}
  1094. X
  1095. XPutLine0(x, y, line)
  1096. Xint x,y;
  1097. Xregister char *line;
  1098. X{
  1099. X    /** Write a zero argument line at location x,y **/
  1100. X
  1101. X    MoveCursor(x,y);
  1102. X    while(*line)
  1103. X      Writechar(*line++);
  1104. X    fflush(stdout);
  1105. X}
  1106. X
  1107. X/*VARARGS2*/
  1108. XPutLine1(x,y, line, arg1)
  1109. Xint x,y;
  1110. Xchar *line;
  1111. Xchar *arg1;
  1112. X{
  1113. X    /** write line at location x,y - one argument... **/
  1114. X
  1115. X    char buffer[VERY_LONG_STRING];
  1116. X
  1117. X    sprintf(buffer, line, arg1);
  1118. X
  1119. X    PutLine0(x, y, buffer);
  1120. X        fflush(stdout);
  1121. X}
  1122. X
  1123. X/*VARARGS2*/
  1124. XPutLine2(x,y, line, arg1, arg2)
  1125. Xint x,y;
  1126. Xchar *line;
  1127. Xchar *arg1, *arg2;
  1128. X{
  1129. X    /** write line at location x,y - one argument... **/
  1130. X
  1131. X    char buffer[VERY_LONG_STRING];
  1132. X
  1133. X    sprintf(buffer, line, arg1, arg2);
  1134. X
  1135. X    PutLine0(x, y, buffer);
  1136. X        fflush(stdout);
  1137. X}
  1138. X
  1139. X/*VARARGS2*/
  1140. XPutLine3(x,y, line, arg1, arg2, arg3)
  1141. Xint x,y;
  1142. Xchar *line;
  1143. Xchar *arg1, *arg2, *arg3;
  1144. X{
  1145. X    /** write line at location x,y - one argument... **/
  1146. X
  1147. X    char buffer[VERY_LONG_STRING];
  1148. X
  1149. X    sprintf(buffer, line, arg1, arg2, arg3);
  1150. X
  1151. X    PutLine0(x, y, buffer);
  1152. X        fflush(stdout);
  1153. X}
  1154. X
  1155. XCleartoEOLN()
  1156. X{
  1157. X    /** clear to end of line **/
  1158. X
  1159. X    if (!_cleartoeoln)
  1160. X        return(-1);
  1161. X
  1162. X    tputs(_cleartoeoln, 1, outchar);
  1163. X    fflush(stdout);  /* clear the output buffer */
  1164. X    return(0);
  1165. X}
  1166. X
  1167. XCleartoEOS()
  1168. X{
  1169. X    /** clear to end of screen **/
  1170. X
  1171. X    if (!_cleartoeos)
  1172. X        return(-1);
  1173. X
  1174. X    tputs(_cleartoeos, 1, outchar);
  1175. X    fflush(stdout);  /* clear the output buffer */
  1176. X    return(0);
  1177. X}
  1178. X
  1179. X
  1180. XRawState()
  1181. X{
  1182. X    /** returns either 1 or 0, for ON or OFF **/
  1183. X
  1184. X    return( _inraw );
  1185. X}
  1186. X
  1187. XRaw(state)
  1188. Xint state;
  1189. X{
  1190. X    /** state is either ON or OFF, as indicated by call **/
  1191. X
  1192. X    if (state == OFF && _inraw) {
  1193. X      (void) ioctl(TTYIN, TCSETAW, &_original_tty);
  1194. X      _inraw = 0;
  1195. X    }
  1196. X    else if (state == ON && ! _inraw) {
  1197. X
  1198. X      (void) ioctl(TTYIN, TCGETA, &_original_tty);    /** current setting **/
  1199. X
  1200. X      (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
  1201. X#ifndef TERMIO
  1202. X      _raw_tty.sg_flags &= ~(ECHO);    /* echo off */
  1203. X      _raw_tty.sg_flags |= CBREAK;    /* raw on    */
  1204. X#else
  1205. X      _raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  1206. X
  1207. X      _raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  1208. X      _raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  1209. X
  1210. X#endif
  1211. X      (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
  1212. X
  1213. X      _inraw = 1;
  1214. X    }
  1215. X}
  1216. X
  1217. Xint
  1218. XReadCh()
  1219. X{
  1220. X    /** read a character with Raw mode set! **/
  1221. X
  1222. X    register int result;
  1223. X    char ch;
  1224. X    result = read(0, &ch, 1);
  1225. X        return((result <= 0 ) ? EOF : ch);
  1226. X}
  1227. X
  1228. Xoutchar(c)
  1229. Xchar c;
  1230. X{
  1231. X    /** output the given character.  From tputs... **/
  1232. X    /** Note: this CANNOT be a macro!              **/
  1233. X
  1234. X    putc(c, stdout);
  1235. X}
  1236. X
  1237. SHAR_EOF
  1238. chmod 0444 src/curses.c || echo "restore of src/curses.c fails"
  1239. echo "x - extracting src/date.c (Text)"
  1240. sed 's/^X//' << 'SHAR_EOF' > src/date.c &&
  1241. X
  1242. Xstatic char rcsid[] = "@(#)$Id: date.c,v 2.6 89/03/25 21:45:58 syd Exp $";
  1243. X
  1244. X/*******************************************************************************
  1245. X *  The Elm Mail System  -  $Revision: 2.6 $   $State: Exp $
  1246. X *
  1247. X *             Copyright (c) 1986, 1987 Dave Taylor
  1248. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1249. X *******************************************************************************
  1250. X * Bug reports, patches, comments, suggestions should be sent to:
  1251. X *
  1252. X *    Syd Weinstein, Elm Coordinator
  1253. X *    elm@dsinc.UUCP            dsinc!elm
  1254. X *
  1255. X *******************************************************************************
  1256. X * $Log:    date.c,v $
  1257. X * Revision 2.6  89/03/25  21:45:58  syd
  1258. X * Initial 2.2 Release checkin
  1259. X * 
  1260. X *
  1261. X ******************************************************************************/
  1262. X
  1263. X/** return the current date and time in a readable format! **/
  1264. X/** also returns an ARPA RFC-822 format date...            **/
  1265. X
  1266. X
  1267. X#include "headers.h"
  1268. X
  1269. X#ifdef BSD
  1270. X#  ifdef TMINSYS
  1271. X#    include <sys/time.h>
  1272. X#  else
  1273. X#    include <time.h>
  1274. X#    include <sys/types.h>
  1275. X#    include <sys/timeb.h>
  1276. X#  endif
  1277. X#else
  1278. X#  include <time.h>
  1279. X#endif
  1280. X
  1281. X#include <ctype.h>
  1282. X
  1283. X#ifdef BSD
  1284. X#undef toupper
  1285. X#undef tolower
  1286. X#endif
  1287. X
  1288. X#define MONTHS_IN_YEAR    11    /* 0-11 equals 12 months! */
  1289. X#define FEB         1    /* 0 = January           */
  1290. X#define DAYS_IN_LEAP_FEB 29    /* leap year only       */
  1291. X
  1292. X#define ampm(n)        (n > 12? n - 12 : n)
  1293. X#define am_or_pm(n)    (n > 11? (n > 23? "am" : "pm") : "am")
  1294. X#define leapyear(year)    ((year % 4 == 0) && (year % 100 != 0))
  1295. X
  1296. Xchar *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
  1297. X          "Fri", "Sat", "" };
  1298. X
  1299. Xchar *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1300. X          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
  1301. X
  1302. Xint  days_in_month[] = { 31,    28,    31,    30,    31,     30, 
  1303. X          31,     31,    30,   31,    30,     31,  -1};
  1304. X
  1305. X#ifdef BSD
  1306. X  char *timezone();
  1307. X#else
  1308. X  extern char *tzname[];
  1309. X#endif
  1310. X
  1311. Xchar *get_arpa_date()
  1312. X{
  1313. X    /** returns an ARPA standard date.  The format for the date
  1314. X        according to DARPA document RFC-822 is exemplified by;
  1315. X
  1316. X                     Mon, 12 Aug 85 6:29:08 MST
  1317. X
  1318. X    **/
  1319. X
  1320. X    static char buffer[SLEN];    /* static character buffer       */
  1321. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  1322. X          *localtime();
  1323. X    long       junk,        /* time in seconds....         */
  1324. X               time();
  1325. X
  1326. X#ifdef BSD
  1327. X# ifndef TZ_MINUTESWEST
  1328. X    struct timeb    loc_time;
  1329. X
  1330. X    junk = time((long *) 0);
  1331. X    ftime(&loc_time);
  1332. X# else
  1333. X    struct  timeval  time_val;        
  1334. X    struct  timezone time_zone;
  1335. X
  1336. X    gettimeofday(&time_val, &time_zone);
  1337. X    junk = time_val.tv_sec;
  1338. X# endif
  1339. X
  1340. X#else
  1341. X    junk = time((long *) 0);    /* this must be here for it to work! */
  1342. X#endif
  1343. X
  1344. X    the_time = localtime(&junk);
  1345. X
  1346. X    sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
  1347. X      arpa_dayname[the_time->tm_wday],
  1348. X      the_time->tm_mday % 32,
  1349. X      arpa_monname[the_time->tm_mon],
  1350. X      the_time->tm_year % 100,
  1351. X      the_time->tm_hour % 24,
  1352. X      the_time->tm_min  % 61,
  1353. X      the_time->tm_sec  % 61,
  1354. X#ifdef BSD
  1355. X#ifdef TZ_MINUTESWEST
  1356. X      timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
  1357. X#else
  1358. X      timezone(loc_time.timezone, the_time->tm_isdst));
  1359. X#endif
  1360. X#else
  1361. X      tzname[the_time->tm_isdst]);
  1362. X#endif
  1363. X    
  1364. X    return( (char *) buffer);
  1365. X}
  1366. X
  1367. Xdays_ahead(days, buffer)
  1368. Xint days;
  1369. Xchar *buffer;
  1370. X{
  1371. X    /** return in buffer the date (Day, Mon Day, Year) of the date
  1372. X        'days' days after today.  
  1373. X    **/
  1374. X
  1375. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  1376. X          *localtime();
  1377. X    long       junk,        /* time in seconds....         */
  1378. X           time();
  1379. X
  1380. X    junk = time((long *) 0);    /* this must be here for it to work! */
  1381. X    the_time = localtime(&junk);
  1382. X
  1383. X    /* increment the day of the week */
  1384. X
  1385. X    the_time->tm_wday = (the_time->tm_wday + days) % 7;
  1386. X
  1387. X    /* the day of the month... */
  1388. X    the_time->tm_mday += days;
  1389. X    
  1390. X    if (the_time->tm_mday > days_in_month[the_time->tm_mon]) {
  1391. X      if (the_time->tm_mon == FEB && leapyear(the_time->tm_year)) {
  1392. X        if (the_time->tm_mday > DAYS_IN_LEAP_FEB) {
  1393. X          the_time->tm_mday -= days_in_month[the_time->tm_mon];
  1394. X          the_time->tm_mon += 1;
  1395. X        }
  1396. X      }
  1397. X      else {
  1398. X        the_time->tm_mday -= days_in_month[the_time->tm_mon];
  1399. X        the_time->tm_mon += 1;
  1400. X      }
  1401. X    }
  1402. X
  1403. X    /* check the month of the year */
  1404. X    if (the_time->tm_mon > MONTHS_IN_YEAR) {
  1405. X      the_time->tm_mon -= MONTHS_IN_YEAR;
  1406. X      the_time->tm_year += 1;
  1407. X    }
  1408. X
  1409. X    /* now, finally, build the actual date string */
  1410. X
  1411. X    sprintf(buffer, "%s, %d %s %d",
  1412. X      arpa_dayname[the_time->tm_wday],
  1413. X      the_time->tm_mday % 32,
  1414. X      arpa_monname[the_time->tm_mon],
  1415. X      the_time->tm_year % 100);
  1416. X}
  1417. X
  1418. Xint
  1419. Xvalid_date(day, mon, year)
  1420. Xchar *day, *mon, *year;
  1421. X{
  1422. X    /** Validate the given date - returns TRUE iff the date
  1423. X        handed is reasonable and valid.  
  1424. X        Ignore month param, okay? 
  1425. X    **/
  1426. X
  1427. X    register int daynum, yearnum;
  1428. X
  1429. X    daynum = atoi(day);
  1430. X    yearnum = atoi(year);
  1431. X    
  1432. X    if (daynum < 1 || daynum > 31) {
  1433. X      dprint(3, (debugfile, 
  1434. X          "Error: day %d is obviously wrong! (valid_date)\n", 
  1435. X              daynum));
  1436. X      return(0);
  1437. X    }
  1438. X    
  1439. X    if (yearnum < 1 || (yearnum > 100 && yearnum < 1900) ||
  1440. X        yearnum > 2000) {
  1441. X      dprint(3, (debugfile, 
  1442. X        "Error: year %d is obviously wrong! (valid_date)\n", 
  1443. X        yearnum));
  1444. X      return(0);
  1445. X    }
  1446. X    
  1447. X    return(1);
  1448. X}
  1449. X
  1450. Xfix_date(entry)
  1451. Xstruct header_rec *entry;
  1452. X{
  1453. X    /** This routine will 'fix' the date entry for the specified
  1454. X        message.  This consists of 1) adjusting the year to 0-99
  1455. X        and 2) altering time from HH:MM:SS to HH:MM am|pm **/ 
  1456. X
  1457. X    if (atoi(entry->year) > 99)     
  1458. X      sprintf(entry->year,"%d", atoi(entry->year) - 1900);
  1459. X
  1460. X    fix_time(entry->time);
  1461. X}
  1462. X
  1463. Xfix_time(timestring)
  1464. Xchar *timestring;
  1465. X{
  1466. X    /** Timestring in format HH:MM:SS (24 hour time).  This routine
  1467. X        will fix it to display as: HH:MM [am|pm] **/
  1468. X
  1469. X    int hour, minute;
  1470. X
  1471. X    sscanf(timestring, "%d:%d", &hour, &minute);
  1472. X
  1473. X    if (hour < 1 || hour == 24) 
  1474. X      sprintf(timestring, "12:%02d am", minute);
  1475. X    else if (hour < 12)
  1476. X      sprintf(timestring, "%d:%02d am", hour, minute);
  1477. X    else if (hour == 12)
  1478. X      sprintf(timestring, "12:%02d pm", minute);
  1479. X    else if (hour < 24)
  1480. X      sprintf(timestring, "%d:%02d pm", hour-12, minute);
  1481. X}
  1482. X
  1483. Xint
  1484. Xcompare_dates(rec1, rec2)
  1485. Xstruct header_rec *rec1, *rec2;
  1486. X{
  1487. X    /** This function works similarly to the "strcmp" function, but
  1488. X        has lots of knowledge about the internal date format...
  1489. X        Apologies to those who "know a better way"...
  1490. X    **/
  1491. X
  1492. X    int month1, day1, year1, hour1, minute1,
  1493. X        month2, day2, year2, hour2, minute2;
  1494. X
  1495. X    year1 = atoi(rec1->year);
  1496. X    year2 = atoi(rec2->year);
  1497. X
  1498. X    if (year1 != year2)
  1499. X      return( year1 - year2 );
  1500. X
  1501. X    /* And HERE's where the performance of this sort dies... */
  1502. X
  1503. X    month1 = month_number(rec1->month);    /* retch...  gag....  */
  1504. X    month2 = month_number(rec2->month);    /*    puke...         */
  1505. X
  1506. X    if (month1 == -1) 
  1507. X      dprint(2, (debugfile,
  1508. X        "month_number failed on month '%s'\n", rec1->month));
  1509. X
  1510. X    if (month2 == -1) 
  1511. X      dprint(2, (debugfile,
  1512. X        "month_number failed on month '%s'\n", rec2->month));
  1513. X
  1514. X    if (month1 != month2)
  1515. X      return( month1 - month2 );
  1516. X
  1517. X    /* back and cruisin' now, though... */
  1518. X
  1519. X    day1 = atoi(rec1->day);     /* unfortunately, 2 is greater than 19  */
  1520. X    day2 = atoi(rec2->day);  /* on a dump string-only compare...     */
  1521. X
  1522. X    if (day1 != day2)
  1523. X      return( day1 - day2 );
  1524. X
  1525. X    /* we're really slowing down now... */
  1526. X
  1527. X    minute1 = minute2 = -1;
  1528. X
  1529. X    sscanf(rec1->time, "%d:%d", &hour1, &minute1);
  1530. X    sscanf(rec2->time, "%d:%d", &hour2, &minute2);
  1531. X
  1532. X    /* did we get the time?  If not, try again */
  1533. X
  1534. X    if (minute1 < 0)
  1535. X      sscanf(rec1->time, "%2d%2d", &hour1, &minute1);
  1536. X
  1537. X    if (minute2 < 0)
  1538. X      sscanf(rec2->time, "%2d%2d", &hour2, &minute2);
  1539. X
  1540. X    /** deal with am/pm, if present... **/
  1541. X
  1542. X    if (strlen(rec1->time) > 3)
  1543. X      if (rec1->time[strlen(rec1->time)-2] == 'p') {
  1544. X       if (hour1 != 12)
  1545. X        hour1 += 12;
  1546. X       }
  1547. X      else {
  1548. X       if (hour1 == 12)
  1549. X        hour1 = 0;
  1550. X       }
  1551. X
  1552. X    if (strlen(rec2->time) > 3)
  1553. X      if (rec2->time[strlen(rec2->time)-2] == 'p') {
  1554. X       if (hour2 != 12)
  1555. X        hour2 += 12;
  1556. X       }
  1557. X      else {
  1558. X       if (hour2 == 12)
  1559. X        hour2 = 0;
  1560. X       }
  1561. X
  1562. X    if (hour1 != hour2)
  1563. X      return( hour1 - hour2 );
  1564. X
  1565. X    return( minute1 - minute2 );        /* ignore seconds... */
  1566. X}
  1567. X
  1568. Xint
  1569. Xcompare_parsed_dates(rec1, rec2)
  1570. Xstruct date_rec rec1, rec2;
  1571. X{
  1572. X    /** This function is very similar to the compare_dates
  1573. X        function but assumes that the two record structures
  1574. X        are already parsed and stored in "date_rec" format.
  1575. X    **/
  1576. X
  1577. X    if (rec1.year != rec2.year)
  1578. X      return( rec1.year - rec2.year );
  1579. X    
  1580. X    if (rec1.month != rec2.month)
  1581. X      return( rec1.month - rec2.month );
  1582. X
  1583. X    if (rec1.day != rec2.day)
  1584. X      return( rec1.day - rec2.day );
  1585. X
  1586. X    if (rec1.hour != rec2.hour)
  1587. X      return( rec1.hour - rec2.hour );
  1588. X
  1589. X    return( rec1.minute - rec2.minute );        /* ignore seconds... */
  1590. X}
  1591. X
  1592. Xint
  1593. Xmonth_number(name)
  1594. Xchar *name;
  1595. X{
  1596. X    /** return the month number given the month name... **/
  1597. X
  1598. X    char ch;
  1599. X
  1600. X    switch (tolower(name[0])) {
  1601. X     case 'a' : if ((ch = tolower(name[1])) == 'p')    return(APRIL);
  1602. X            else if (ch == 'u') return(AUGUST);
  1603. X            else return(-1);    /* error! */
  1604. X    
  1605. X     case 'd' : return(DECEMBER);
  1606. X     case 'f' : return(FEBRUARY);
  1607. X     case 'j' : if ((ch = tolower(name[1])) == 'a') return(JANUARY);
  1608. X            else if (ch == 'u') {
  1609. X                  if ((ch = tolower(name[2])) == 'n') return(JUNE);
  1610. X              else if (ch == 'l') return(JULY);
  1611. X              else return(-1);        /* error! */
  1612. X                }
  1613. X            else return(-1);        /* error */
  1614. X     case 'm' : if ((ch = tolower(name[2])) == 'r') return(MARCH);
  1615. X            else if (ch == 'y') return(MAY);
  1616. X            else return(-1);        /* error! */
  1617. X     case 'n' : return(NOVEMBER);
  1618. X     case 'o' : return(OCTOBER);
  1619. X     case 's' : return(SEPTEMBER);
  1620. X     default  : return(-1);
  1621. X    }
  1622. X}
  1623. X
  1624. X#ifdef SITE_HIDING
  1625. X
  1626. Xchar *get_ctime_date()
  1627. X{
  1628. X    /** returns a ctime() format date, but a few minutes in the 
  1629. X        past...(more cunningness to implement hidden sites) **/
  1630. X
  1631. X    static char buffer[SLEN];    /* static character buffer       */
  1632. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  1633. X          *localtime();
  1634. X    long       junk,        /* time in seconds....         */
  1635. X           time();
  1636. X#ifdef BSD
  1637. X    struct  timeval  time_val;        
  1638. X    struct  timezone time_zone;
  1639. X#endif
  1640. X
  1641. X#ifdef BSD
  1642. X    gettimeofday(&time_val, &time_zone);
  1643. X    junk = time_val.tv_sec;
  1644. X#else
  1645. X    junk = time((long *) 0);    /* this must be here for it to work! */
  1646. X#endif
  1647. X    the_time = localtime(&junk);
  1648. X
  1649. X    sprintf(buffer, "%s %s %d %02d:%02d:%02d %d",
  1650. X      arpa_dayname[the_time->tm_wday],
  1651. X      arpa_monname[the_time->tm_mon],
  1652. X      the_time->tm_mday % 32,
  1653. X      min(the_time->tm_hour % 24, (rand() % 24)),
  1654. X      min(abs(the_time->tm_min  % 61 - (rand() % 60)), (rand() % 60)),
  1655. X      min(abs(the_time->tm_sec  % 61 - (rand() % 60)), (rand() % 60)),
  1656. X      the_time->tm_year % 100 + 1900);
  1657. X    
  1658. X    return( (char *) buffer);
  1659. X}
  1660. X
  1661. X#endif
  1662. SHAR_EOF
  1663. chmod 0444 src/date.c || echo "restore of src/date.c fails"
  1664. echo "x - extracting src/delete.c (Text)"
  1665. sed 's/^X//' << 'SHAR_EOF' > src/delete.c &&
  1666. X
  1667. Xstatic char rcsid[] = "@(#)$Id: delete.c,v 2.6 89/03/25 21:46:00 syd Exp $";
  1668. X
  1669. X/*******************************************************************************
  1670. X *  The Elm Mail System  -  $Revision: 2.6 $   $State: Exp $
  1671. X *
  1672. X *             Copyright (c) 1986, 1987 Dave Taylor
  1673. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1674. X *******************************************************************************
  1675. X * Bug reports, patches, comments, suggestions should be sent to:
  1676. X *
  1677. X *    Syd Weinstein, Elm Coordinator
  1678. X *    elm@dsinc.UUCP            dsinc!elm
  1679. X *
  1680. X *******************************************************************************
  1681. X * $Log:    delete.c,v $
  1682. X * Revision 2.6  89/03/25  21:46:00  syd
  1683. X * Initial 2.2 Release checkin
  1684. X * 
  1685. X *
  1686. X ******************************************************************************/
  1687. X
  1688. X/**  Delete or undelete files: just set flag in header record! 
  1689. X     Also tags specified message(s)...
  1690. X
  1691. X**/
  1692. X
  1693. X#include "headers.h"
  1694. X
  1695. Xchar *show_status();
  1696. X
  1697. Xdelete_msg(real_del, update_screen)
  1698. Xint real_del, update_screen;
  1699. X{
  1700. X    /** Delete current message.  If real-del is false, then we're
  1701. X        actually requested to toggle the state of the current
  1702. X        message... **/
  1703. X
  1704. X    if (real_del)
  1705. X      headers[current-1]->status |= DELETED;
  1706. X    else if (ison(headers[current-1]->status, DELETED))
  1707. X      clearit(headers[current-1]->status, DELETED);
  1708. X    else
  1709. X      setit(headers[current-1]->status, DELETED);
  1710. X
  1711. X    if (update_screen)
  1712. X      show_msg_status(current-1);
  1713. X}
  1714. X
  1715. Xundelete_msg(update_screen)
  1716. Xint update_screen;
  1717. X{
  1718. X    /** clear the deleted message flag **/
  1719. X
  1720. X    clearit(headers[current-1]->status, DELETED);
  1721. X
  1722. X    if (update_screen)
  1723. X      show_msg_status(current-1);
  1724. X}
  1725. X
  1726. Xshow_msg_status(msg)
  1727. Xint msg;
  1728. X{
  1729. X    /** show the status of the current message only.  **/
  1730. X
  1731. X    char tempbuf[3];
  1732. X
  1733. X    strcpy(tempbuf, show_status(headers[msg]->status));
  1734. X
  1735. X    if (on_page(msg)) {
  1736. X      MoveCursor(((compute_visible(msg+1)-1) % headers_per_page) + 4, 2);
  1737. X      if (msg+1 == current && !arrow_cursor) {
  1738. X        StartBold();
  1739. X        Writechar( tempbuf[0] );
  1740. X        EndBold();
  1741. X      }
  1742. X      else
  1743. X        Writechar( tempbuf[0] );
  1744. X    }
  1745. X}
  1746. X
  1747. Xint
  1748. Xtag_message(update_screen)
  1749. Xint update_screen;
  1750. X{
  1751. X    /** Tag current message and return TRUE.
  1752. X        If already tagged, untag it and return FALSE. **/
  1753. X
  1754. X    int istagged;
  1755. X
  1756. X    if (ison(headers[current-1]->status, TAGGED)) {
  1757. X      clearit(headers[current-1]->status, TAGGED);
  1758. X      istagged = FALSE;
  1759. X    } else {
  1760. X      setit(headers[current-1]->status, TAGGED);
  1761. X      istagged = TRUE;
  1762. X    }
  1763. X
  1764. X    if(update_screen)
  1765. X        show_msg_tag(current-1);
  1766. X    return(istagged);
  1767. X}
  1768. X
  1769. Xshow_msg_tag(msg)
  1770. Xint msg;
  1771. X{
  1772. X    /** show the tag status of the current message only.  **/
  1773. X
  1774. X    if (on_page(msg)) {
  1775. X      MoveCursor(((compute_visible(msg+1)-1) % headers_per_page) + 4, 4);
  1776. X      if (msg+1 == current && !arrow_cursor) {
  1777. X        StartBold();
  1778. X        Writechar( ison(headers[msg]->status, TAGGED)? '+' : ' ');
  1779. X        EndBold();
  1780. X      }
  1781. X      else
  1782. X        Writechar( ison(headers[msg]->status, TAGGED)? '+' : ' ');
  1783. X    }    
  1784. X}
  1785. X
  1786. Xshow_new_status(msg)
  1787. Xint msg;
  1788. X{
  1789. X    /** If the specified message is on this screen, show
  1790. X        the new status (could be marked for deletion now,
  1791. X        and could have tag removed...)
  1792. X    **/
  1793. X
  1794. X    if (on_page(msg)) 
  1795. X      if (msg+1 == current && !arrow_cursor) {
  1796. X        StartBold();
  1797. X        PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  1798. X           2, "%s%c", show_status(headers[msg]->status),
  1799. X           ison(headers[msg]->status, TAGGED )? '+' : ' ');
  1800. X        EndBold();
  1801. X      }
  1802. X      else
  1803. X        PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  1804. X           2, "%s%c", show_status(headers[msg]->status),
  1805. X           ison(headers[msg]->status, TAGGED )? '+' : ' ');
  1806. X}
  1807. SHAR_EOF
  1808. chmod 0444 src/delete.c || echo "restore of src/delete.c fails"
  1809. echo "x - extracting src/domains.c (Text)"
  1810. sed 's/^X//' << 'SHAR_EOF' > src/domains.c &&
  1811. X
  1812. Xstatic char rcsid[] = "@(#)$Id: domains.c,v 2.6 89/03/25 21:46:01 syd Exp $";
  1813. X
  1814. X/*******************************************************************************
  1815. X *  The Elm Mail System  -  $Revision: 2.6 $   $State: Exp $
  1816. X *
  1817. X *             Copyright (c) 1986, 1987 Dave Taylor
  1818. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1819. X *******************************************************************************
  1820. X * Bug reports, patches, comments, suggestions should be sent to:
  1821. X *
  1822. X *    Syd Weinstein, Elm Coordinator
  1823. X *    elm@dsinc.UUCP            dsinc!elm
  1824. X *
  1825. X *******************************************************************************
  1826. X * $Log:    domains.c,v $
  1827. X * Revision 2.6  89/03/25  21:46:01  syd
  1828. X * Initial 2.2 Release checkin
  1829. X * 
  1830. X *
  1831. X ******************************************************************************/
  1832. X
  1833. X/** This file contains all the code dealing with the expansion of 
  1834. X    domain based addresses in Elm.  It uses the file "domains" as
  1835. X    defined in the sysdefs.h file.
  1836. X
  1837. X    From a file format and idea in "uumail" - designed by Stan Barber.
  1838. X**/
  1839. X
  1840. X#include <ctype.h>
  1841. X
  1842. X#include "headers.h"
  1843. X
  1844. X#ifdef BSD
  1845. X# undef toupper
  1846. X# undef tolower
  1847. X#endif
  1848. X
  1849. X/** define the various characters that we can encounter after a "%" sign
  1850. X    in the template file...
  1851. X**/
  1852. X
  1853. X#define USERNAME    'U'    /* %U = the name of the remote user */
  1854. X#define RMTMNAME    'N'    /* %N = the remote machine name     */
  1855. X#define FULLNAME    'D'    /* %D = %N + domain info given      */
  1856. X#define NPATH        'R'    /* %R = path to %N from pathalias   */
  1857. X#define PPATH        'P'    /* %P = path to 'P' from pathalias  */
  1858. X#define OBSOLETE    'S'    /* %S = (used to be suffix string)  */
  1859. X
  1860. X/** and finally some characters that are allowed in user/machine names **/
  1861. X
  1862. X#define okay_others(c)    (c == '-' || c == '^' || c == '$' || c == '_')
  1863. X
  1864. X/** and some allowed ONLY in the username field **/
  1865. X
  1866. X#define special_chars(c)    (c == '%' || c == ':')
  1867. X
  1868. Xchar *find_path_to(), *expand_domain(), *match_and_expand_domain();
  1869. Xchar *strcpy(), *strcat(), *strtok();
  1870. Xunsigned long sleep();
  1871. Xvoid rewind();
  1872. X          
  1873. Xopen_domain_file()
  1874. X{
  1875. X    if ((domainfd = fopen(domains, "r")) == NULL) {
  1876. X      dprint(2, (debugfile,"Warning: can't open file %s as domains file\n", 
  1877. X        domains));
  1878. X    }
  1879. X    else {
  1880. X      dprint(3, (debugfile, 
  1881. X            "Opened '%s' as the domain database\n\n", domains));
  1882. X    }
  1883. X    
  1884. X    /* if it fails it'll instantiate domainfd to NULL which is
  1885. X       exactly what we want to have happen!! */
  1886. X}
  1887. X
  1888. Xchar *expand_domain(buffer)
  1889. Xchar *buffer;
  1890. X{
  1891. X    /** Expand the address 'buffer' based on the domain information, 
  1892. X        if any.  Returns NULL if it can't expand it for any reason.
  1893. X    **/
  1894. X
  1895. X    char name[NLEN], address[NLEN], domain[NLEN];
  1896. X    char *match_and_expand_domain();
  1897. X
  1898. X    if (domainfd == NULL) return(NULL);    /* no file present! */
  1899. X
  1900. X    if (explode(buffer, name, address, domain)) 
  1901. X      return( match_and_expand_domain(domain, name, address) );
  1902. X    else {    /* invalid format - not "user@host.domain" */
  1903. X      dprint(2,  (debugfile,
  1904. X         "Invalid format for domain expansion: %s (expand_domain)\n", 
  1905. X           buffer));
  1906. X      return(NULL);
  1907. X    }
  1908. X}    
  1909. X
  1910. Xint
  1911. Xexplode(buffer, name, address, domain)
  1912. Xchar *buffer, *name, *address, *domain;
  1913. X{
  1914. X    /** Break buffer, if in format name@machine.domain, into the
  1915. X        component parts, otherwise return ZERO and don't worry
  1916. X        about the values of the parameters!
  1917. X    **/
  1918. X    
  1919. X    register int i, j = 0;
  1920. X
  1921. X    /** First get the name... **/
  1922. X
  1923. X    for (i=0; buffer[i] != '@'; i++) {
  1924. X      if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) && ! 
  1925. X        special_chars(buffer[i]))
  1926. X        return(0);            /* invalid character in string! */
  1927. X      name[i] = buffer[i];
  1928. X    }
  1929. X
  1930. X    name[i++] = '\0';
  1931. X
  1932. X    /** now let's get the machinename **/
  1933. X
  1934. X    while (buffer[i] != '.') {
  1935. X      if (! isalnum(buffer[i]) && ! okay_others(buffer[i]))
  1936. X         return(0);            /* invalid character in string! */
  1937. X      address[j++] = buffer[i++];
  1938. X    }
  1939. X    address[j] = '\0';
  1940. X
  1941. X    j = 0;
  1942. X
  1943. X    /** finally let's get the domain information (there better be some!) **/
  1944. X
  1945. X    while (buffer[i] != '\0') {
  1946. X      if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) && 
  1947. X            buffer[i] != '.')
  1948. X        return(0);              /* an you fail again, bozo! */
  1949. X      domain[j++] = toupper(buffer[i]);
  1950. X      i++;
  1951. X    }
  1952. X
  1953. X    domain[j] = '\0';
  1954. X    
  1955. X    return(j);        /* if j == 0 there's no domain info! */
  1956. X}
  1957. X        
  1958. Xchar *match_and_expand_domain(domain, name, machine)
  1959. Xchar *domain, *name, *machine;
  1960. X{
  1961. X    /** Given the domain, try to find it in the domain file and
  1962. X           if found expand the entry and return the result as a 
  1963. X        character string...
  1964. X    **/
  1965. X
  1966. X    static char address[SLEN];
  1967. X    char   buffer[SLEN], domainbuff[NLEN];
  1968. X    char   field1[NLEN], field2[NLEN], field3[NLEN];
  1969. X    char   *path, *template, *expanded, *mydomain, *strtok();
  1970. X    int    matched = 0, in_percent = 0;
  1971. X    register int i, j = 0;
  1972. X
  1973. X    address[j] = '\0';
  1974. X
  1975. X    domainbuff[0] = '\0';
  1976. X    mydomain = (char *) domainbuff;            /* set up buffer etc */
  1977. X
  1978. X    do { 
  1979. X      rewind(domainfd);                   /* back to ground zero! */
  1980. X
  1981. X      if (strlen(mydomain) > 0) {           /* already in a domain! */
  1982. X        mydomain++;                       /* skip leading '.' */
  1983. X        while (*mydomain != '.' && *mydomain != ',') 
  1984. X          mydomain++;                   /* next character   */
  1985. X        if (*mydomain == ',')
  1986. X          return (NULL);                /* didn't find domain!  */
  1987. X      }
  1988. X      else
  1989. X        sprintf(mydomain, "%s,", domain);        /* match ENTIRELY! */
  1990. X
  1991. X    /* whip through file looking for the entry, please... */
  1992. SHAR_EOF
  1993. echo "End of part 12"
  1994. echo "File src/domains.c is continued in part 13"
  1995. echo "13" > s2_seq_.tmp
  1996. exit 0
  1997.  
  1998.